#ifndef COMMONIMPL_H__COMMON__INCLUDED_
#define COMMONIMPL_H__COMMON__INCLUDED_

namespace MinCOM
{

	namespace Private
	{

		class ReferenceDecl
		{

			ReferenceDecl(const ReferenceDecl&);
			ReferenceDecl& operator =(const ReferenceDecl&);

		protected:

			ReferenceDecl()
				: numRef_(0)
			{
			}

		protected:

			unsigned long numRef_;

		};

	} // namespace Private

	template
	<
		class T
	>
	class CommonImpl
		: virtual public Private::ReferenceDecl
		, public T
	{

		CommonImpl(const CommonImpl&);
		CommonImpl& operator =(const CommonImpl&);

	protected:

		CommonImpl()
			: ReferenceDecl()
		{
		}

		virtual ~CommonImpl() {}

	public:

		// Cast tools
		T* CastType()
		{
			return static_cast< T* >( this );
		}

		ICommon* GetCommon()
		{
			return static_cast< ICommon* >( this );
		}

		// ICommon section
		virtual unsigned long AddRef()
		{
			return ++ReferenceDecl::numRef_;                        
		}

		virtual unsigned long Release()
		{
			--ReferenceDecl::numRef_;

			if (ReferenceDecl::numRef_ == 0)
			{
				delete this;
				return 0;
			}

			return ReferenceDecl::numRef_;
		}

		result QueryInterface(RefIid iid, void** ppObject)
		{
			if ( iid == IID_ICommon )
				*ppObject = GetCommon();

			else
			{
				*ppObject = NULL;
				return _E_NOINTERFACE;
			}

			GetCommon()->AddRef();
			return _S_OK;
		}

	};

}

#endif // !COMMONIMPL_H__COMMON__INCLUDED_
